/**
 * WangSong 2009-6-14 下午02:42:08 修改获取数据源信息方式,所有单数据源请求都从文件获取数据源信息
 */
package cn.biplam.common.client;

import java.io.Serializable;
import java.rmi.RemoteException;

import cn.biplam.common.interfaces.DbResourceServer;
import cn.biplam.common.paramters.SysName;
import cn.biplam.common.tools.DEBUG;
import cn.biplam.common.tools.RMITOOLS;
import cn.biplam.common.tools.TOOLS;
import cn.biplam.common.wrapper.ErrorMessage;
import cn.biplam.common.wrapper.KvMap;

/**
 * 
 * 数据源信息类
 * @author 	WangSong Mar 3, 2009 5:32:41 PM
 * @version 1.0
 */
public class DbResource implements Serializable{

	/**系统默认数据源名称*/
	public static final String RT = "RT";
	/**系统参数服务数据源*/
	public static final String CONFIG = "CONFIG";
	/**系统日志服务数据源*/
	public static final String LOG = "LOG";
	/**系统名称解析服务数据源*/
	public static final String SNR = "SNR";

	private static final long serialVersionUID = -8685079134517733700L;

	private String name;					//数据源名称
	private String desc;					//数据源描述 
	private String ip;				        //数据源ip地址
	private String dsType;                 //数据源类型
	private String dbType;                 //数据库类型
	private String sid;					//数据源sid
	private String mainDb;                 //主数据库
	private String port;                   //端口
	private String user;				//数据库用户名
	private String password;				//数据库密码

	/**默认数据源信息*/
	private static KvMap<String,String> rt;
	private static KvMap<String,String> config;
	private static KvMap<String,String> log;
	private static KvMap<String,String> snr;

	/**
	 * 从本地JDA文件中初始化默认数据源
	 * @throws ErrorMessage 
	 */
	public DbResource() throws ErrorMessage{
		this.createByFile(RT);
	}

	/**
	 * 使用默认数据源创建
	 * @param 	dsName 默认数据源名称
	 * @throws 	RemoteException
	 * @throws ErrorMessage 
	 */
	public DbResource(String dsName) throws ErrorMessage{
		if(dsName==null)
			throw new ErrorMessage("DbResource name is null!");
		if(	dsName.equals(RT) || 
				dsName.equals(CONFIG) || 
				dsName.equals(LOG) ||
				dsName.equals(SNR))
			this.createByFile(dsName);
		else
			this.createByServer(DbResource.RT,dsName);
	}
	
	/**
	 * 创建数据源
	 * @param dsName 数据源名称
	 * @param localFile true:使用配置文件创建数据源
	 *                  false:使用默认数据源从服务器端创建数据源
	 * @throws ErrorMessage 
	 */
	public DbResource(String dsName,boolean localFile) throws ErrorMessage{
		if(dsName==null)
			throw new ErrorMessage("DbResource name is null!");
		if(localFile){
			this.createByFile(dsName);
		}else{
			this.createByServer(DbResource.RT,dsName);
		}
	}

	/**
	 * 指定默认数据源创建
	 * @param 	defaultDsName  	默认数据源名称
	 * @param 	dsName  			需查询的数据源名称
	 * @throws 	RemoteException
	 * @throws ErrorMessage 
	 */
	public DbResource(String defaultDsName,String dsName) throws  ErrorMessage{
		if(dsName==null)
			throw new ErrorMessage("DbResource name is null!");
		if(defaultDsName==null)
			throw new ErrorMessage("Default DbResource name is null!");
		this.createByServer(defaultDsName,dsName);
	}

	/**
	 * 指定默认数据源和独立数据源名称,从服务器获取数据源的信息
	 * @param 	defaultDbResorceName  	默认数据源名称
	 * @param 	dbResouce   		需查询的数据源
	 * @throws 	RemoteException 
	 * @throws ErrorMessage 
	 */
	private void createByServer(String defaultDbResorceName,String dbResouce) throws  ErrorMessage{
		try {
			DbResourceServer dbResourceServer=(DbResourceServer)RMITOOLS.getInstance("DbResourceServer");
			KvMap<String, String> kvMap = dbResourceServer.get(defaultDbResorceName, dbResouce);
			if(kvMap != null){
				this.setInfo(kvMap);
			}else{
				throw new ErrorMessage("Cannot get DbResource("+dbResouce+") from Server.");
			}
		} catch (RemoteException e) {
			throw new ErrorMessage(e,"Get dbr from Server failed!");
		}
	}

	/**
	 * 从本地文件初始化数据源<BR>
	 * 		注:(在运行客户端的JDA配置文件，并非服务器端)
	 * @param dsName  数据源分类标识
	 * @throws ErrorMessage 
	 */
	private void createByFile(String dsName) throws ErrorMessage{
		KvMap<String, String> kv=null;
		String trgDsName=dsName;
		for(int i=0;i<=3;i++){
			/**取系统固化数据源信息数据源的信息RT、CONFIG、LOG、SNR*/
			kv=this.switchDefaultDs(trgDsName);
			if("3".equalsIgnoreCase(kv.getByKey("dsType"))){
				if(i==3)
					throw new ErrorMessage("Other type DbResource nesting over 3 level!");
				else
					trgDsName=kv.getByKey("name");
			}
		}
		this.setInfo(kv);
		/**如果数据源名字为空，则证明数据源信息不完整，抛出异常*/
		if(this.name==null){
			throw new ErrorMessage("Cannot get DbResource info from property file.");
		}
	}

	private KvMap<String, String> switchDefaultDs(String dsName) throws ErrorMessage{
		if(dsName.equalsIgnoreCase(RT)){
			return this.getRT();
		}else if(dsName.equalsIgnoreCase(CONFIG)){
			return this.getConfig();
		}else if(dsName.equalsIgnoreCase(LOG)){
			return this.getLog();
		}else if(dsName.equalsIgnoreCase(SNR)){
			return this.getSnr();
		}else{
			return this.initFromFile(dsName);
		}
	}

	/**
	 * 从JDA文件中获取RT的配置
	 * @return
	 * @throws ErrorMessage
	 */
	private KvMap<String, String> getRT() throws ErrorMessage{
		if(rt==null){
			rt=initFromFile(DbResource.RT);
		}
//		this.printCaller();
		return rt;
	}
	
	/**
	 * 打印调用RT数据源的类(用于性能调优)
	 */
	@SuppressWarnings("unused")
	private void printCaller(){
		try {
			throw new ErrorMessage("");
		} catch (ErrorMessage e) {
			DEBUG.println("【Call】");
			StackTraceElement[] stack=e.getStackTrace();
			for(int i=0;i<stack.length;i++){
				String[] as=stack[i].toString().split("\\.");
				if(stack[i].toString().startsWith("cn.biplam.common.client.DbResource")){
					continue;
				}
				if(as.length>0){
					if(	as[0].equalsIgnoreCase("cn") && 
						as[1].equalsIgnoreCase("biplam")){
						DEBUG.println("\t"+stack[i].toString());
					}
				}
			}
		}
	}

	/**
	 * 从JDA文件中获取Config的配置
	 * @return
	 * @throws ErrorMessage
	 */
	private KvMap<String, String> getConfig() throws ErrorMessage{
		if(config==null){
			config=initFromFile(DbResource.CONFIG);
		}
		return config;
	}

	/**
	 * 从JDA文件中获取Log的配置
	 * @return
	 * @throws ErrorMessage
	 */
	private KvMap<String, String> getLog() throws ErrorMessage{
		if(log==null){
			log=initFromFile(DbResource.LOG);
		}
		return log;
	}

	/**
	 * 从JDA文件中获取Snr的配置
	 * @return
	 * @throws ErrorMessage
	 */
	private KvMap<String, String> getSnr() throws ErrorMessage{
		if(snr==null){
			snr=initFromFile(DbResource.SNR);
		}
		return snr;
	}

	/**
	 * 从JDS属性文件中获取指定数据源的熟悉，存入KvMap
	 * @param dsName
	 * @return
	 * @throws ErrorMessage
	 */
	private KvMap<String,String> initFromFile(String dsName)  throws ErrorMessage{
		KvMap<String, String> set = TOOLS.getValueByProperty(SysName.PropertiesPathJda);
		KvMap<String,String> kv = new KvMap<String,String>();
		kv.put("name", set.getByKey(dsName+".name"));
		kv.put("desc", set.getByKey(dsName+".desc"));
		kv.put("dsType",set.getByKey(dsName+".dsType"));
		kv.put("dbType", set.getByKey(dsName+".dbType"));
		kv.put("ip", set.getByKey(dsName+".ip"));
		kv.put("port", set.getByKey(dsName+".port"));
		kv.put("sid", set.getByKey(dsName+".sid"));
		kv.put("mainDb", set.getByKey(dsName+".mainDb"));
		kv.put("user", set.getByKey(dsName+".user"));
		kv.put("password", set.getByKey(dsName+".password"));
		return kv;
	}

	/**
	 * 用传入的KvMap中的键值对初始化数据源属性
	 * @param kvMap
	 */
	private void setInfo(KvMap<String, String> kvMap){
		this.name = kvMap.getByKey("name");
		this.desc =kvMap.getByKey("desc");
		this.dsType = kvMap.getByKey("dsType");
		this.dbType = kvMap.getByKey("dbType");
		this.ip = kvMap.getByKey("ip");
		this.port = kvMap.getByKey("port");
		this.sid = kvMap.getByKey("sid");
		this.mainDb = kvMap.getByKey("mainDb");
		this.user = kvMap.getByKey("user");
		this.password = kvMap.getByKey("password");
	}

	/**
	 * 返回数据源名称
	 * @return String
	 */
	public String getDsname() {
		return this.name;
	}

	/**
	 * 返回数据源描述
	 * @return
	 * @throws RemoteException
	 */
	public String getDsdesc() {
		return desc;
	}

	/**
	 * 返回数据源地址
	 * @return
	 * @throws RemoteException
	 */
	public String getIp() {
		return ip;
	}

	/**
	 * 返回数据源端口
	 * @return
	 * @throws RemoteException
	 */
	public String getPort() {
		return port;
	}

	/**
	 * 返回数据库实例名
	 * @return
	 * @throws RemoteException
	 */
	public String getDssid() {
		return sid;
	}

	/** 
	 * 返回用户名
	 * @return
	 * @throws RemoteException
	 */
	public String getUsername() {
		return user;
	}

	/**
	 * 返回密码
	 * @return
	 * @throws RemoteException
	 */
	public String getPassword() {
		return password;
	}

	/**
	 * 功能    数据库类型
	 * @return
	 * @throws RemoteException
	 */
	public String getDbtype() {
		return dbType;
	}

	/**
	 * 返回主数据库名称
	 * @return
	 * @throws RemoteException
	 */
	public String getSMaindb() {
		return mainDb;
	}

	/**
	 * 返回数据源名称
	 * @param dsname
	 * @throws RemoteException
	 */
	public void setDsname(String dsname){
		name = dsname;
	}

	/**
	 * 返回数据源类型
	 * @return
	 */
	public String getDsType() {
		return dsType;
	}
}
